﻿using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Org.BouncyCastle.Asn1.Pkcs;
using Quartz;
using Serilog;
using System.Text;
using WCS_Core_Configuration;
using WCS_Quartz_Task;
using WCS_Quartz_Task._631;
using WCS_Service.DomianService.Models;
using WCS_Service.Enums;
using WCS_Service.Models.SerialNetModel;
using WCS_Service.ProtocolServices.Interface;
using WCS_Utility.ConstString;

namespace WCS_Service.ProtocolServices
{
    /// <summary>
    /// 光通信服务
    /// </summary>
    public class OpticalService : IProtocolService
    {
        public bool OpticalComCreatFlag { get; set; }

        private DateTime? _creatComTime;

        public bool isSerialNet { get; set; }
        public int equipmentId { get; set; }

        private readonly IQuartzJobProcess _quartzJobProcess;
        #region 属性
        public event Func<string,int, Task> ReceiveMsgBusinessEvent;
        public event Func<int, ConEquipmentState, Task> OppositeConChange;
        #endregion

        public OpticalService(IQuartzJobProcess quartzJobProcess)
        {
            _quartzJobProcess = quartzJobProcess;
        }

        public async Task ReceiveMsgAsync(ClientDataReceiveEventArgs e)
        {
            await MsgAnalysisAsync(e.Data);
        }

        public async Task<string> SendMsgSplicingAsync(string msg)
        {
            return await Task.Run(() => 
            {
                if (string.IsNullOrEmpty(msg))
                {
                    Log.Error($"Optoical发送到数据为空!");
                    return null;
                }
                var sendMsg = msg;
                return sendMsg;
            });
        }

        private async Task MsgAnalysisAsync(Memory<byte> data)
        {
            try 
            {
                var message = Encoding.UTF8.GetString(data.ToArray());
                if (message is null)
                {
                    Log.Error($"光通信接收数据错误!");
                    return;
                }
                await HeartbeatMsgProcess();
                if (message != ConstStringData.HeartBeatMsg)
                {
                    //把透传的内容交给对应的透传内容协议解析
                    ReceiveMsgBusinessEvent?.Invoke(message, equipmentId);
                }
            }
            catch (Exception ex) 
            {
                Log.Error($"光通信数据转换失败!{ex.Message}");
                return;
            }
        }
        private async Task RevieveMsgProcessAsync(string msgData)
        {
            await Task.Run(() => 
            {
                if (msgData != ConstStringData.HeartBeatMsg)
                {
                    var flag = MsgLengthCheck(msgData);
                    //把透传的内容交给对应的透传内容协议解析
                    ReceiveMsgBusinessEvent?.Invoke(msgData, equipmentId);
                }
            });
        }

        private bool MsgLengthCheck(string msg)
        {
            var info = JsonConvert.DeserializeObject<OpticalInfoModel>(msg);
            if (info is null)
            {
                return false;
            }
            if (info.dataLen != info.data.Length)
            { 
                return true;
            }
            return false;
        }

        /// <summary>
        /// 心跳包处理
        /// </summary>
        /// <returns></returns>
        private async Task HeartbeatMsgProcess()
        {
            if (!OpticalComCreatFlag)
            {
                OpticalComCreatFlag = true;
                _creatComTime = DateTime.Now;
                await CreatHeartbeatCheckJobAsync();
                OppositeConChange?.Invoke(equipmentId, ConEquipmentState.Connect);
                return;
            }
            _creatComTime = DateTime.Now;
        }
        private List<string> GetMsgInfo(string message)
        {
            if (string.IsNullOrEmpty(message))
            {
                return null;
            }
            if (!message.Contains(ConstStringData.Termination))
            {
                return null;
            }
            var infos = message.Split(ConstStringData.Termination)?.ToList();
            if (infos is null || infos.Count < 2)
            {
                return null;
            }
            if (!infos.Last().Contains(ConstStringData.OpticalFunCode))
            {
                infos.Remove(infos.Last());
            }
            return infos;
        }

        private async Task CreatHeartbeatCheckJobAsync()
        {
            var jobDetail = JobBuilder.Create<HeartbeatJob>().WithIdentity(ConstStringData.OpticalOppositeCheck + equipmentId,
                    ConstStringData.OpticalOppositeCheck).Build();

            jobDetail.JobDataMap.Put("heartbeatCheck", HeatbeatCheckerAsync);
            var trigger = TriggerBuilder.Create()
                                        .WithSimpleSchedule(m =>
                                        {
                                            m.WithIntervalInSeconds(2).RepeatForever();
                                        })
                                        .Build();

            //添加心跳任务
            await _quartzJobProcess.AddJobAsync(jobDetail, trigger);
        }
        /// <summary>
        /// 检查心跳包是否在有效时间内
        /// </summary>
        /// <returns></returns>
        private async Task HeatbeatCheckerAsync()
        {
            if (!OpticalComCreatFlag || _creatComTime is null)
            {
                await _quartzJobProcess.DeleteJobAsync(ConstStringData.OpticalOppositeCheck + equipmentId,
                    ConstStringData.OpticalOppositeCheck);
                OpticalComCreatFlag = false;
                _creatComTime = null;
                OppositeConChange?.Invoke(equipmentId, ConEquipmentState.DisConnect);
                return;
            }
            else if ((DateTime.Now - _creatComTime.Value).TotalSeconds > 20)
            {
                await _quartzJobProcess.DeleteJobAsync(ConstStringData.OpticalOppositeCheck + equipmentId,
                    ConstStringData.OpticalOppositeCheck);
                OpticalComCreatFlag = false;
                _creatComTime = null;
                OppositeConChange?.Invoke(equipmentId, ConEquipmentState.DisConnect);
                return; 
            }
        }

        public async Task<string> SetSerialNetDataAsync(object data)
        {
            var creatData = data as SerialOpticalComModel;
            if (creatData is null) return null;
            OpticalInfoModel info = new OpticalInfoModel();
            info.funCode = creatData.funCode;
            info.number = creatData.reqCode;
            info.type = creatData.type;
            info.EqCode = AppSettingsConstVars.WcsEqCode;
            info.data = creatData.msg;
            info.dataLen = creatData.msg.Length;

            return JsonConvert.SerializeObject(info);
        }
    }
}
